﻿/******************************************************************************
 * 【本类功能概述】                                 					      *
 *  版权所有（C）2017- 匠梦科技                                         *
 *  保留所有权利。                                                            *
 ******************************************************************************
 *  作者 : <hughjk>
 *  创建时间:2019年5月19日 14:59:28
 *  文件描述:扩展代码
 *****************************************************************************/

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables;
using Object = UnityEngine.Object;

namespace Util
{
    public static class UtilSys
    {
        public static Timer.TimerProc toDelay<T>(this object tf, float time, Func<T> func, Action<T> Return)
        {
            return Timer.Instance.Add(time, () =>
            {
                if (func != null)
                {
                    Return.Invoke(func.Invoke());
                }
            });
        }

        /// <summary>
        /// 延迟执行
        /// </summary>
        public static Timer.TimerProc toDelay(this object tf, float time, Action func)
        {
            return Timer.Instance.Add(time, () =>
            {
                if (func != null)
                {
                    func.Invoke();
                }
            });
        }
        public static Timer.TimerProc toDelay<T>(this T tf, float time, Action<T> func)
        {
            if (tf.isNull())
            {
                debug.log(debug.Level.error_3, "NUll");
                return null;
            }
            return Timer.Instance.Add(time, () =>
            {
                if (func != null)
                {
                    func.Invoke(tf);
                }
            });
        }
        /// <summary>
        /// 延迟执行
        /// </summary>
        public static Timer.TimerProc toDelay<T>(this object tf, float time, Action<T> func, T t)
        {
            return Timer.Instance.Add(time, () =>
            {
                if (func != null)
                {
                    func.Invoke(t);
                }
            });
        }

        /// <summary>
        /// 延迟执行
        /// </summary>
        public static Timer.TimerProc toDelay<T, T1>(this object tf, float time, Action<T, T1> func, T t, T1 t1)
        {
            return Timer.Instance.Add(time, () =>
            {
                if (func != null)
                {
                    func.Invoke(t, t1);
                }
            });
        }

        public static Timer.TimerProc toDelay<T, T1, T2>(this object tf, float time, Action<T, T1, T2> func, T t, T1 t1, T2 t2)
        {
            return Timer.Instance.Add(time, () =>
            {
                if (func != null)
                {
                    func.Invoke(t, t1, t2);
                }
            });
        }

        public static void SetOrAdd<T1, T2>(this Dictionary<T1, T2> dic, T1 key, T2 v)
        {
            if (dic.ContainsKey(key))
            {
                dic[key] = v;
            }
            else
            {
                dic.Add(key, v);
            }
        }

        public static T2 GetOrAdd<T1, T2>(this Dictionary<T1, T2> dic, T1 key, T2 defaults = default(T2))
        {
            T2 v;
            if (dic.TryGetValue(key, out v))
            {
                return v;
            }
            else
            {
                v = defaults;
                dic.Add(key, v);
                return v;
            }
        }
        public static void Adds<T1>(this List<T1> list, params T1[] key)
        {
            list.AddRange(key);
        }
        public static void Adds<T1>(this List<T1> list, List<T1> key)
        {
            list.AddRange(key);
        }
        //添加唯一对象
        public static void AddOnly<T1>(this List<T1> list, T1 key)
        {
            if (list.IndexOf(key) < 0)
            {
                list.Add(key);
            }
        }
        public static T asT<T>(this object obj) where T : class
        {
            return obj as T;
        }

        public static bool isT<T>(this object obj) where T : class
        {
            return obj is T;
        }
        //--------------------------------------------------------------------
        public static bool isTrue(this object obj)
        {
            if (obj == null)
            {
                return false;
            }
            return true;
        }
        public static bool isTrue(this object[] obj)
        {
            if (obj == null || obj.Length == 0)
            {
                return false;
            }
            return true;
        }
        public static bool isTrue(this string obj)
        {
            if (obj == null)
            {
                return false;
            }
            if (obj.Length == 0)
            {
                return false;
            }
            return true;
        }
        public static bool isTrue(this Object[] obj)
        {
            if (obj == null || obj.Length == 0)
            {
                return false;
            }
            return true;
        }
        public static bool isTrue(this Object obj)
        {
            if (obj == null || obj.GetInstanceID() == 0)
            {
                return false;
            }
            return true;
        }
        //--------------------------------------------------------------------
        public static bool isNull(this Object obj)
        {
            if (obj == null || obj.GetInstanceID() == 0)
            {
                return true;
            }
            return false;
        }
        public static bool isNull(this Object[] obj)
        {
            if (obj == null || obj.Length == 0)
            {
                return true;
            }
            return false;
        }
        public static bool isNulls(this string obj)
        {
            if (obj == null || obj.Length == 0)
            {
                return true;
            }
            return false;
        }
        public static bool isNull(this object obj)
        {
            if (obj == null)
            {
                return true;
            }
            return false;
        }
        public static bool isNull(this Timer.TimerClock obj)
        {
            if (obj == null)
            {
                return true;
            }
            if (obj.maxcd == 0)
            {
                return true;
            }
            return false;
        }
        public static bool isNull(this object[] obj)
        {
            if (obj == null || obj.Length == 0)
            {
                return true;
            }
            return false;
        }


        //-----------------------------------------------------------------------------

        public static void toInvoke(this Action action)
        {
            if (action.isTrue())
            {
                try
                {
                    action.Invoke();
                }
                catch (Exception e)
                {
                    debug.log(e);
                }
            }
        }

        public static bool toInvoke(this Func<bool> action)
        {
            if (action.isTrue())
            {
                return action.Invoke();
            }
            return false;
        }
        public static void byInvokeAll<T>(this List<T> l, Action<T> action)
        {
            for (int i = l.Count - 1; i >= 0; i--)
            {
                action.toInvoke(l[i]);
            }
        }

        public static void byInvokeAll<T>(this T[] l, Action<T> action)
        {
            for (int i = l.Length - 1; i >= 0; i--)
            {
                action.toInvoke(l[i]);
            }
        }
        public static T EndNode<T>(this List<T> l)
        {
            if (l.Count >= 1)
            {
                return l[l.Count - 1];
            }
            return default(T);
        }
        public static T EndNode<T>(this T[] l)
        {
            if (l.Length >= 1)
            {
                return l[l.Length - 1];
            }
            return default(T);
        }

        public static void byInvokeAll<K, V>(this Dictionary<K, V> dic, Action<K, V> action)
        {
            var e = dic.GetEnumerator();
            while (e.MoveNext())
            {
                action.Invoke(e.Current.Key, e.Current.Value);
            }
        }
        public static void byKeyInvokeAll<K, V>(this Dictionary<K, V> dic, Action<K> action)
        {
            List<K> ks = new List<K>(dic.Keys);
            for (int i = ks.Count - 1; i >= 0; i--)
            {
                action.Invoke(ks[i]);
            }
        }
        public static void byValueInvokeAll<K, V>(this Dictionary<K, V> dic, Action<V> action)
        {
            var e = dic.Values.GetEnumerator();
            while (e.MoveNext())
            {
                action.Invoke(e.Current);
            }
        }
        public static RaycastHit2D[] RemoveDuplicates(this RaycastHit2D[] l)
        {
            Mlist<RaycastHit2D> ls = new Mlist<RaycastHit2D>();
            bool isadd = true;
            for (int i = 0; i < l.Length; i++)
            {
                var cl = l[i];
                isadd = true;
                for (int j = 0; j < ls.Count; j++)
                {
                    var cls = ls[j];
                    if (cls.transform.Equals(cl.transform))
                    {
                        isadd = false;
                        break;
                    }
                }
                if (isadd)
                {
                    ls.Add(cl);
                }
            }
            return ls;
        }

        public static Timer.TimerProc toInvoke(this Action action, float timer)
        {
            return Timer.Adds(timer, () =>
            {
                if (action.isTrue())
                {
                    action.Invoke();
                }
            });
        }

        public static void toInvoke<T>(this Action<T> action, T t)
        {
            if (action.isTrue())
            {
                debug.tryCatch(() =>//包裹一下~防止卡死
                {
                    action.Invoke(t);
                });
            }
        }

        public static void toInvoke<T1, T2>(this Action<T1, T2> action, T1 t1, T2 t2)
        {
            if (action.isTrue())
            {
                action.Invoke(t1, t2);
            }
        }

        public static Dictionary<string, T> toNameDic<T>(this List<T> _list) where T : Object
        {
            Dictionary<string, T> Dic = new Dictionary<string, T>();
            for (int i = 0; i < _list.Count; i++)
            {
                Dic.SetOrAdd(_list[i].name, _list[i]);
            }
            return Dic;
        }

        public static Dictionary<string, T2> toNameDic<T, T2>(this List<T> _list) where T : Object where T2 : Object
        {
            Dictionary<string, T2> Dic = new Dictionary<string, T2>();
            for (int i = 0; i < _list.Count; i++)
            {
                Dic.SetOrAdd(_list[i].name, _list[i] as T2);
            }
            return Dic;
        }

        /// <summary>
        /// 拷贝队列
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="_list"></param>
        /// <returns></returns>
        public static List<T> CopyList<T>(this List<T> _list)
        {
            List<T> temp = new List<T>();
            for (int i = 0; i < _list.Count; i++)
            {
                temp.Add(_list[i]);
            }
            return temp;
        }

        public static void Add<T>(this List<T> _list, T[] atrr)
        {
            for (int i = 0; i < atrr.Length; i++)
            {
                _list.Add(atrr[i]);
            }
        }

        public static T toOne<T>(this List<T> ts)
        {
            T t = default(T);
            if (ts.Count > 0)
            {
                return ts[0];
            }
            return t;
        }

        public static T toEnd<T>(this List<T> ts)
        {
            T t = default(T);
            if (ts.Count > 0)
            {
                return ts[ts.Count - 1];
            }
            return t;
        }

        public static List<T2> toType<T, T2>(this List<T> ts) where T : Object where T2 : Object
        {
            List<T2> t2 = new List<T2>();
            for (int i = 0; i < ts.Count; i++)
            {
                t2.Add(ts[i] as T2);
            }
            return t2;
        }

        public static T[] ConvertMutiToSingle<T>(this T[][] arr)
        {
            var l = new List<T>();
            for (int i = 0; i < arr.Length; ++i)
            {
                for (int j = 0; j < arr[i].Length; ++j)
                {
                    l.Add(arr[i][j]);
                }
            }

            return l.ToArray();
        }

        public static void ExChange<T>(ref T t1, ref T t2)
        {
            var tmp = t1;
            t1 = t2;
            t2 = tmp;
        }

        public static void LogArrElements<T>(this T[] arr)
        {
            for (int i = 0; i < arr.Length; ++i)
            {
                Debug.Log("element " + i + " " + arr[i] + "\n");
            }
        }

        public static void Add(this int[] arr, int[] other)
        {
            for (int i = 0; i < arr.Length; ++i)
            {
                arr[i] += other[i];
            }
        }

        public static void Remove<T>(this List<T> list, System.Func<T, bool> func)
        {
            for (int i = 0; i < list.Count; i++)
            {
                if (func(list[i]))
                {
                    list.RemoveAt(i);
                    break;
                }
            }
        }

        public static T[] SubArray<T>(this T[] data, int index, int length)
        {
            var result = new T[length];
            Array.Copy(data, index, result, 0, length);
            return result;
        }

        public static int GetEnumCount<T>() where T : struct
        {
            return Enum.GetValues(typeof(T)).Length;
        }

        public static float GetDistSqr(Vector2 pos1, Vector2 pos2)
        {
            float x = pos1.x - pos2.x;
            float y = pos1.y - pos2.y;

            return x * x + y * y;
        }
    }

    public static class UtilUnity
    {
        public static T GetComponent<T>(this Transform v, ref T com) where T : Component
        {
            com = v.GetComponent<T>();
            return com;
        }
        public static T GetComponent<T>(this Component v, ref T com) where T : Component
        {
            com = v.GetComponent<T>();
            return com;
        }
        public static Component GetComponent<T1, T2>(this Component v, ref T1 com1, ref T2 com2) where T1 : Component where T2 : Component
        {
            com1 = v.GetComponent<T1>();
            com2 = v.GetComponent<T2>();
            return v;
        }
        public static T GetOrAddComponent<T>(this Transform v) where T : Component
        {
            T t = v.GetComponent<T>();
            if (!t)
            {
                t = v.gameObject.AddComponent<T>();
            }
            return t;
        }
        public static Component GetOrAddComponent(this Transform v, Type type)
        {
            Component t = v.GetComponent(type);
            if (!t)
            {
                t = v.gameObject.AddComponent(type);
            }
            return t;
        }
        public static T toInstantiate<T>(this T t, Transform Par = null, float time = 0) where T : Component
        {
            T newt = GameObject.Instantiate(t);
            if (Par)
            {
                newt.transform.parent = Par;
                newt.transform.toResetLocal();
            }
            if (time > 0)
            {
                Timer.Adds(time, () =>
                {
                    GameObject.Destroy(newt);
                });
            }
            return newt;
        }

        //排序
        public static void toSort(this Transform tf)
        {
            if (tf.childCount > 1)
            {
                List<Transform> tfs = new List<Transform>();
                for (int i = 0; i < tf.childCount; i++)
                {
                    tfs.Add(tf.GetChild(i));
                }
                if (tfs.Count > 1)
                {
                    tfs.Sort((t1, t2) => { return t1.name.CompareTo(t2.name); });
                    for (int i = 0; i < tfs.Count; i++)
                    {
                        tfs[i].SetSiblingIndex(i);
                    }
                }
            }
        }
        public static Transform FindNode(this Transform node, string name)
        {
            if (node.name.Equals(name))
            {
                return node;
            }

            for (int i = 0; i < node.childCount; i++)
            {
                Transform t = node.GetChild(i);
                t = FindNode(t, name);

                if (t != null)
                {
                    return t;
                }
            }

            return null;
        }
        public static T FindOrNew<T>(this Transform tf) where T : Component
        {
            T newtf = tf.GetComponentInChildren<T>();
            if (!newtf)
            {
                string Name = typeof(T).ToString().toSplit('.').toEnd();
                newtf = new GameObject(Name).transform.GetOrAddComponent<T>();
                newtf.transform.parent = tf;
                newtf.transform.toResetLocal(tf);
            }

            return newtf;
        }

        public static Transform FindOrNew(this Transform tf, string Name)
        {
            Transform newtf = tf.Find(Name);
            if (!newtf)
            {
                newtf = new GameObject(Name).transform;
                newtf.toResetLocal(tf);
            }
            return newtf;
        }

        public static Transform FindPathOrNew(this Transform tf, string[] Paths)
        {
            string[] p = Paths;
            var cur = tf;
            for (int i = 0; i < p.Length; i++)
            {
                cur = cur.FindOrNew(p[i]);
            }
            return cur;
        }

        public static void toResetLocal(this Transform tf, Transform par)
        {
            tf.parent = par;
            tf.toResetLocal();
        }

        public static void toResetLocal(this Transform tf)
        {
            tf.localPosition = Vector3.zero;
            tf.localEulerAngles = Vector3.zero;
            tf.localScale = Vector3.one;
        }

        public static void toReset(this Transform tf)
        {
            tf.position = Vector3.zero;
            tf.eulerAngles = Vector3.zero;
            tf.localScale = Vector3.one;
        }

        public static void toGoSetPos(this Vector3 v3, params Component[] gos)
        {
            for (int i = 0; i < gos.Length; i++)
            {
                gos[i].transform.position = v3;
            }
        }

        public static void SetPosition(this LineRenderer line, params Vector3[] pos)
        {
            line.positionCount = pos.Length;
            for (int i = 0; i < pos.Length; i++)
            {
                line.SetPosition(i, pos[i]);
            }
        }

        public static void setChildActive(this Component obj, bool Active, params Component[] coms)
        {
            if (obj)
            {
                for (int i = 0; i < coms.Length; i++)
                {
                    coms[i].setActive(Active);
                }
            }
        }

        public static void setActive(this Component obj, bool Active)
        {
            if (obj)
            {
                obj.gameObject.setActive(Active);
            }
        }
        public static void setActive(this Component[] obj, bool Active)
        {
            for (int i = 0; i < obj.Length; i++)
            {
                if (obj[i])
                {
                    obj[i].gameObject.setActive(Active);
                }
            }

        }

        public static void setActive(this Transform obj, bool Active)
        {
            if (obj)
            {
                obj.gameObject.setActive(Active);
            }
        }

        public static void setActive(this GameObject obj, bool Active)
        {
            if (obj)
            {
                if (obj.activeSelf != Active)
                {
                    obj.SetActive(Active);
                }
            }
        }

        public static Component SetPos(this Component tf, Vector3 pos, Component bases = null)
        {
            if (tf)
            {
                tf.transform.position = pos;
            }
            else if (bases)
            {
                tf = GameObject.Instantiate(bases);
                tf.transform.position = pos;
            }
            return tf;
        }

        public static GameObject SetPos(this GameObject tf, Vector3 pos, GameObject bases = null)
        {
            if (tf)
            {
                tf.transform.position = pos;
            }
            else if (bases)
            {
                tf = GameObject.Instantiate(bases);
                tf.transform.position = pos;
            }
            return tf;
        }

        public static void _SetX(this Transform tf, float x)
        {
            Vector3 pos = tf.position;
            pos.x = x;
            tf.position = pos;
        }

        public static void _SetY(this Transform tf, float y)
        {
            Vector3 pos = tf.position;
            pos.y = y;
            tf.position = pos;
        }

        public static void _SetZ(this Transform tf, float z)
        {
            Vector3 pos = tf.position;
            pos.z = z;
            tf.position = pos;
        }

        public static void Mute(this PlayableDirector playable, string _trackName)
        {
            var rm = TimeLineRuntimeMuter.Instance;
            rm.playableDirector = playable;
            rm.Mute(_trackName);
        }

        public static void Mute(this PlayableDirector playable, int _trackIndex)
        {
            var rm = TimeLineRuntimeMuter.Instance;
            rm.playableDirector = playable;
            rm.Mute(_trackIndex);
        }

        public static void UnMute(this PlayableDirector playable, string _trackName)
        {
            var rm = TimeLineRuntimeMuter.Instance;
            rm.playableDirector = playable;
            rm.UnMute(_trackName);
        }

        public static void UnMute(this PlayableDirector playable, int _trackIndex)
        {
            var rm = TimeLineRuntimeMuter.Instance;
            rm.playableDirector = playable;
            rm.UnMute(_trackIndex);
        }

        public static float RotateZ(this float r)
        {
            int f = r < 0 ? -1 : 1;
            for (int i = 0; i < 361 * f; i += (90 * f))
            {
                var c = (r - i).toAbs();
                if (c <= 45)
                {
                    r = r - i;
                    return r;
                }
            }
            return r;
        }


        //方便编辑器加载预设
        public static GameObject LoadInstantiate(string path)
        {
            GameObject obj = null;
            var Lobj = Resources.Load(path) as GameObject;
            bool isInstantiate = true;
#if UNITY_EDITOR
            if (!UnityEditor.EditorApplication.isPlaying)
            {
                isInstantiate = false;
                obj = UnityEditor.PrefabUtility.InstantiatePrefab(Lobj) as GameObject;
            }
#endif
            if (isInstantiate)
            {
                obj = GameObject.Instantiate(Lobj);
            }
            return obj;
        }
    }

    public static class UtilPhysics
    {
    }
    public class SaveTransformInfo
    {
        public Transform tf;
        public Transform par;
        public Vector3 pos;
        public Vector3 size;
        public Vector3 EulerAngle;

        public void Save(Transform _tf)
        {
            tf = _tf;
            par = _tf.parent;
            pos = _tf.localPosition;
            size = _tf.localScale;
            EulerAngle = _tf.localEulerAngles;
        }
        public void Restore()
        {
            tf.parent = par;
            tf.localPosition = pos;
            tf.localScale = size;
            tf.localEulerAngles = EulerAngle;
        }

    }
    /// <summary>
    /// 执行队列
    /// </summary>
    public class PerformQueue
    {
        private int m_id = 0;
        private readonly List<Action<Action>> m_list = new List<Action<Action>>();
        private readonly Action m_finish;
        private string Name;
        public uint Id;

        public PerformQueue(Action finish = null, string name = null)
        {
            m_finish = finish;
            Name = name;
            Id = debug.Sole;
            if (Name != null)
            {
                debug.log(Id, Name, "Str  PQ");
            }
        }

        public void Add(Action<Action> action)
        {
            m_list.Add(action);
        }

        public void Next()
        {
            try
            {
                if (m_id >= m_list.Count)
                {
                    Over();
                    return;
                }
                m_list[m_id++].Invoke(Next);
            }
            catch (System.Exception ex)
            {
                debug.log(ex);
            }
        }

        public void Over()
        {
            m_id = 0;
            m_list.Clear();
            if (Name != null)
            {
                debug.log(Id, Name, "End PQ");
            }
            if (m_finish != null)
            {
                m_finish.Invoke();
            }
        }
    }

    public class TimePerformQueue
    {
        public class Node
        {
            public float time;//延迟执行
            public Action action;//执行

            public Node(float time, Action action)
            {
                this.time = time;
                this.action = action;
            }
        }

        private int m_id = 0;
        private readonly List<Node> m_list = new List<Node>();
        private readonly Action m_finish;
        private string Name;
        public uint Id;

        public TimePerformQueue(Action finish = null, string name = null)
        {
            m_finish = finish;
            Name = name;
            Id = debug.Sole;
            if (Name != null)
            {
                debug.log(Id, Name, "Str  TPQ");
            }
        }

        //延迟时间,执行事件
        public void Add(float time, Action action)
        {
            m_list.Add(new Node(time, action));
        }

        public void Add(Node node)
        {
            m_list.Add(node);
        }

        public void Next()
        {
            try
            {
                if (m_list.Count <= 0)
                {
                    Over();
                    return;
                }
                var node = m_list[0];
                m_list.RemoveAt(0);
                node.action.Invoke();
                Timer.Instance.Add(node.time, () =>//执行N秒后，并且开启下一个
                {
                    Next();
                });
            }
            catch (System.Exception ex)
            {
                debug.log(ex);
            }
        }

        public void Over()
        {
            m_id = 0;
            m_list.Clear();
            if (Name != null)
            {
                debug.log(Id, Name, "End TPQ");
            }
            if (m_finish != null)
            {
                m_finish.Invoke();
            }
        }
    }

    /// <summary>
    /// 计划任务
    /// </summary>
    public class TaskPlan
    {
        private readonly Action m_finish;
        private readonly Dictionary<string, bool> m_dic = new Dictionary<string, bool>();
        private string Name;
        public uint Id;

        public TaskPlan(Action finish = null, string name = null)
        {
            this.m_finish = finish;
            Name = name;
            Id = debug.Sole;
            if (Name != null)
            {
                debug.log(Id, Name, "Str TP");
            }
        }

        public void Add(string name)
        {
            if (!m_dic.ContainsKey(name))
            {
                m_dic.Add(name, false);
            }
        }

        public void Finish(string name)
        {
            //m_dic[name] = true;
            m_dic.Remove(name);
            if (IsAllFinish())
            {
                m_dic.Clear();
                if (Name != null)
                {
                    debug.log(Id, Name, "End TP");
                }
                if (m_finish != null)
                {
                    m_finish.Invoke();
                }
            }
        }

        public bool IsAllFinish()
        {
            if (m_dic.Count > 0)
            {
                return false;
            }
            //List<bool> list = new List<bool>(m_dic.Values);
            //int num = list.Count;
            //for (int i = 0; i < num; i++)
            //{
            //    if (!list[i])
            //    {
            //        return false;
            //    }
            //}
            //var e = m_dic.GetEnumerator();
            //while (e.MoveNext())
            //{
            //    if (!e.Current.Value)
            //    {
            //        return false;
            //    }
            //}
            return true;
        }

        public int IsFinishNum()
        {
            int n = 0;
            n = m_dic.Count;
            //var e = m_dic.GetEnumerator();
            //while (e.MoveNext())
            //{
            //    if (e.Current.Value == false)
            //    {
            //        n++;
            //    }
            //}
            return n;
        }

        public List<string> GetAllKey()
        {
            return new List<string>(m_dic.Keys);
        }
    }
    public class FuncList<T>
    {
        public Dictionary<int, Func<T>> Actions = new Dictionary<int, Func<T>>();
        public int addKey = 0;
        public int curKey = 0;
        public Func<T>[] Arr = new Func<T>[0];

        public void Add(int key, Func<T> action)
        {
            if (Actions.ContainsKey(key))
            {
                Actions[key] = action;
            }
            else
            {
                Actions.Add(key, action);
            }
            Arr = new List<Func<T>>(Actions.Values).ToArray();
        }

        public int Add(Func<T> action)
        {
            int ckey = addKey;
            Actions.Add(addKey, action);
            addKey++;
            Arr = new List<Func<T>>(Actions.Values).ToArray();
            return ckey;
        }

        public T Invoke(int key)
        {
            if (Actions.ContainsKey(key))
            {
                return Actions[curKey].Invoke();
            }
            else
            {
                return default(T);
            }
        }

        public void Invoke(Action<int, T> action)
        {
            for (int i = Arr.Length - 1; i >= 0; i--)
            {
                action.toInvoke(i, Arr[i].Invoke());
            }
        }

        private int GetVkey(Func<T> v)
        {
            var e = Actions.GetEnumerator();
            int key = -1;
            while (e.MoveNext())
            {
                if (e.Current.Value == v)
                {
                    key = e.Current.Key;
                    break;
                }
            }
            return key;
        }

        public bool Remove(Func<T> v)
        {
            int key = GetVkey(v);
            if (key < 0)
            {
                return false;
            }

            bool isok = Actions.Remove(key);
            Timer.Instance.NextFrame(() => { Arr = new List<Func<T>>(Actions.Values).ToArray(); });
            return isok;
        }

        public bool Remove(int key)
        {
            bool isok = Actions.Remove(key);
            Timer.Instance.NextFrame(() => { Arr = new List<Func<T>>(Actions.Values).ToArray(); });
            return isok;
        }
    }

    public class ActionList
    {
        public Dictionary<int, Action> Actions = new Dictionary<int, Action>();
        public int addKey = 0;
        public int curKey = 0;
        public Action[] Arr = new Action[0];

        public void Add(int key, Action action)
        {
            if (Actions.ContainsKey(key))
            {
                Actions[key] = action;
            }
            else
            {
                Actions.Add(key, action);
            }
            Arr = new List<Action>(Actions.Values).ToArray();
        }

        public Action Next(int key)
        {
            curKey = key;

            if (Actions.ContainsKey(key))
            {
                return Actions[key];
            }
            return null;
        }

        public int Add(Action action)
        {
            int ckey = addKey;
            Actions.Add(addKey, action);
            addKey++;
            Arr = new List<Action>(Actions.Values).ToArray();
            return ckey;
        }

        public void Next()
        {
            if (Actions.ContainsKey(curKey))
            {
                Actions[curKey].Invoke();
            }
            curKey++;
        }

        public void Invoke(int key)
        {
            if (Actions.ContainsKey(key))
            {
                Actions[curKey].Invoke();
            }
        }

        private bool isInvokeChange = false;
        private bool isInvoke = false;

        public void Invoke()
        {
            isInvokeChange = false;
            isInvoke = true;
            for (int i = Arr.Length - 1; i >= 0; i--)
            {
                Arr[i].toInvoke();
            }
            if (isInvokeChange)//队列变化执行完成,马上对齐
            {
                isInvokeChange = false;
                Arr = new List<Action>(Actions.Values).ToArray();
            }
            isInvoke = false;
        }

        private int GetVkey(Action v)
        {
            var e = Actions.GetEnumerator();
            int key = -1;
            while (e.MoveNext())
            {
                if (e.Current.Value == v)
                {
                    key = e.Current.Key;
                    break;
                }
            }
            return key;
        }
        public void Clear()
        {
            Actions.Clear();
            Arr = new Action[0];
            addKey = 0;
            curKey = 0;
        }
        public bool Remove(Action v)
        {
            int key = GetVkey(v);
            if (key < 0)
            {
                return false;
            }
            bool isok = Actions.Remove(key);
            if (isok)
            {
                InvokeInRemoveUpdata();
            }
            return isok;
        }

        public bool Remove(int key)
        {
            bool isok = Actions.Remove(key);
            if (isok)
            {
                InvokeInRemoveUpdata();
            }
            return isok;
        }

        private void InvokeInRemoveUpdata()
        {
            if (isInvoke)//在执行的过程中,删除节点
            {
                isInvokeChange = true;
            }
            else
            {
                Arr = new List<Action>(Actions.Values).ToArray();
            }
        }
    }

    public class ActionList<T>
    {
        public Dictionary<int, Action<T>> Actions = new Dictionary<int, Action<T>>();
        public int addKey = 0;
        public int curKey = 0;

        public void Add(int key, Action<T> action)
        {
            if (Actions.ContainsKey(key))
            {
                Actions[key] = action;
            }
            else
            {
                Actions.Add(key, action);
            }
        }

        public Action<T> Next(int key)
        {
            curKey = key;
            Action<T> action;
            if (Actions.ContainsKey(curKey))
            {
                return action = Actions[curKey];
            }
            return null;
        }

        public int Add(Action<T> action)
        {
            int ckey = addKey;
            Actions.Add(ckey, action);
            addKey++;
            return ckey;
        }

        public void Next(T data)
        {
            if (Actions.ContainsKey(curKey))
            {
                Actions[curKey].Invoke(data);
            }
            curKey++;
        }

        public void Invoke(int key, T data)
        {
            if (Actions.ContainsKey(key))
            {
                Actions[key].Invoke(data);
            }
        }

        public void Invoke(T data)
        {
            var e = Actions.GetEnumerator();
            while (e.MoveNext())
            {
                e.Current.Value.Invoke(data);
            }
        }

        private int GetVkey(Action<T> v)
        {
            var e = Actions.GetEnumerator();
            int key = -1;
            while (e.MoveNext())
            {
                if (e.Current.Value == v)
                {
                    key = e.Current.Key;
                    break;
                }
            }
            return key;
        }

        public void Remove(Action<T> v)
        {
            int key = GetVkey(v);
            if (key < 0)
            {
                return;
            }
            Remove(key);
        }

        public void Remove(int key)
        {
            Timer.Instance.Add(0, () => { Actions.Remove(key); });
        }
    }

    //决策
    public class DecisionAction
    {
        public Mdic<int, TBag<Func<bool>, Action>> dic = new Mdic<int, TBag<Func<bool>, Action>>();
        private int ckey = -1;

        public int Add(Func<bool> verdict, Action execute)
        {
            ckey++;
            dic.SetOrAdd(ckey, new TBag<Func<bool>, Action>(verdict, execute));
            return ckey;
        }

        public void Remove(int key)
        {
            dic.Remove(key);
        }

        public void Execute()
        {
            dic.ForValue((bog) =>
            {
                if (bog.t1.toInvoke())
                {
                    bog.t2.toInvoke();
                }
            });
        }
    }

    [Serializable]
    public class Mlist<T> : List<T>
    {
        public static implicit operator Mlist<T>(T[] real)
        {
            Mlist<T> obscured = new Mlist<T>();
            for (int i = 0; i < real.Length; i++)
            {
                obscured.Add(real[i]);
            }
            return obscured;
        }

        public static implicit operator T[](Mlist<T> real)
        {
            return real.ToArray();
        }

        public Mlist<T2> toList<T2>(Func<T, T2> func)
        {
            Mlist<T2> t2s = new Mlist<T2>();
            for (int i = 0; i < this.Count; i++)
            {
                var cur = this[i];
                var nt2 = func(cur);
                t2s.Add(nt2);
            }
            return t2s;
        }

        public void AddOrSet(T t)
        {
            int id = this.IndexOf(t);
            if (id < 0)
            {
                Add(t);
            }
        }
    }

    [Serializable]
    public class Mdic<T1, T2> : Dictionary<T1, T2>
    {
        public T2[] v;
        public T1[] k;

        public T2[] ValueArray()
        {
            if (v == null || v.Length != Count)
            {
                v = new T2[Count];
            }
            Values.CopyTo(v, 0);
            return v;
        }

        public T1[] KeyArray()
        {
            if (k == null || k.Length != Count)
            {
                k = new T1[Count];
            }
            Keys.CopyTo(k, 0);
            return k;
        }

        public void For(Action<T1, T2> action)
        {
            var e = GetEnumerator();
            while (e.MoveNext())
            {
                var cur = e.Current;
                action.toInvoke(cur.Key, cur.Value);
            }
        }

        public void ForValue(Action<T2> action)
        {
            var e = Values.GetEnumerator();
            while (e.MoveNext())
            {
                action.toInvoke(e.Current);
            }
        }

        public void ForKey(Action<T1> action)
        {
            var e = Keys.GetEnumerator();
            while (e.MoveNext())
            {
                action.toInvoke(e.Current);
            }
        }
    }

}